﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Drawing;
using System.Drawing.Imaging;
using Team6_Algorithms.AidingClasses;

namespace Team6_Algorithms.Binary
{
    /// <summary>
    /// Made by Pascal Schotman && Dylan Snel
    /// Class holding certain methods to make the blobs on a binairy pixels grow.
    /// </summary>
    public class Dilation
    {
        /// <summary>
        /// This function will dilate the given bitmap.
        /// The input image has to be black - white ( binary ) for this function.
        /// </summary>
        /// <param name="srcImage">Bitmap to dilate</param>
        /// <returns>Returns dilated bitmap</returns>
        public Bitmap Dilate(Bitmap srcImage)
        {
            Bitmap returnImage = new Bitmap(srcImage.Width, srcImage.Height);
            BitmapData srcData = srcImage.LockBits(new Rectangle(0, 0,
                srcImage.Width, srcImage.Height), ImageLockMode.ReadOnly,
                PixelFormat.Format24bppRgb);
            BitmapData desData = returnImage.LockBits(new Rectangle(0, 0, returnImage.Width,
                returnImage.Height), ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);

            // Dilate mask
            byte[,] mask = new byte[5, 5] { 
                {0,0,1,0,0},
                {0,1,1,1,0},
                {1,1,1,1,1},
                {0,1,1,1,0},
                {0,0,1,0,0}
            };
            
            int size = 5;
            byte max, clrValue;
            int rad = size / 2;
            int i, j;

            unsafe
            {
                for (int y = rad; y < desData.Height - rad; y++)
                {
                    byte* ptr = (byte*)srcData.Scan0 + (y * srcData.Stride);
                    byte* dstPtr = (byte*)desData.Scan0 + (y * srcData.Stride);
                    for (int x = rad; x < desData.Width - rad; x++)
                    {
                        max = 0;
                        clrValue = 0;
                        for (int maskY = 0; maskY < 5; maskY++)
                        {
                            i = maskY - rad;
                            byte* tempPtr = (byte*)srcData.Scan0 +
                                ((y + i) * srcData.Stride);

                            for (int maskX = 0; maskX < 5; maskX++)
                            {
                                j = maskX - rad;
                                clrValue = (byte)((tempPtr[x * 3 + j] +
                                    tempPtr[x * 3 + j + 1] + tempPtr[x * 3 + j + 2]) / 3);
                                if (max < clrValue)
                                {
                                    if (mask[maskY, maskX] != 0)
                                        max = clrValue;
                                }
                            }
                        }
                        dstPtr[0] = dstPtr[1] = dstPtr[2] = max;
                        ptr += 3;
                        dstPtr += 3;
                    }
                }
            }
            srcImage.UnlockBits(srcData);
            returnImage.UnlockBits(desData);
            return returnImage;
        }

        /// <summary>
        /// Makes the blobs in a binairy image grow.
        /// </summary>
        /// <param name="PP">An array of PixelPoints representing the binairy image</param>
        /// <param name="size">Represents the amount you want to make the blob grow</param>
        /// <param name="width">the image width</param>
        /// <param name="height">the image heigt</param>
        /// <returns>A new PixelPoint array with grown blobs</returns>
        public static PixelPoint[,] Dilate(PixelPoint[,] PP, int size, int width, int height)
        {
            PixelPoint[,] PP2 =(PixelPoint[,]) PP.Clone();
            int halfsize = (size - 1) / 2;
            for (int y = halfsize; y < (height - halfsize); y++)
            {
                for (int x = halfsize; x < (width - halfsize); x++)
                {
                    if (PP[x, y].id == 1)
                    {
                        for (int y2 = -halfsize; y2 < halfsize; y2++)
                        {
                            for (int x2 = -halfsize; x2 < halfsize; x2++)
                            {
                                PP2[x + x2, y + y2] = new PixelPoint(x + x2, y + y2, 1, 255, 255, 255, null);
                            }
                        }
                    }

                }
            }
            return PP2;
        }


    }
}
